package com.demo.datastructure.stack;

import java.util.HashMap;
import java.util.Map;

/**
 * @author ljr
 * @version 1.0
 * @description: 计算器实现
 * @date 2021/10/9 10:16
 */
public class CalculatorStack {


   public static Map<Character, Integer> perc = new HashMap(){
        {
            put('*',2);
            put('/',2);
            put('+',1);
            put('-',1);
            put('(',0);
        }
    };



    /*public static void main(String[] args) {
        System.out.println(Integer.valueOf('/'));
    }*/


    public static void main(String[] args) {
        String calculator = "7/(2+5)*3+2+5+(2-3-1+2*5)";
        int result = getCount3(calculator);
        System.out.println(result);
    }

    private static int getCount(String calculator) {
        MyStack<Integer> num = new MyStack();
        MyStack<Character> calculatorStack = new MyStack();
        char[] values = calculator.toCharArray();
        for(int i = 0; i < values.length; i++){
            if(!Character.isDigit(values[i])) continue;
            if(calculatorStack.isEmpty()){
                if(i != 0) calculatorStack.push(values[i-1]);
                num.push((int)values[i] - (int)('0'));
            }else {
                if (perc.get(values[i - 1]) > perc.get(calculatorStack.peek())) {
                    int operand1 = num.pop();
                    int operand2 = (int) values[i] - (int) ('0');
                    char token = values[i - 1];
                    int result = doMain(token, operand1, operand2);
                    num.push(result);
                } else {
                    if (perc.get(values[i - 1]) < perc.get(calculatorStack.peek())) {
                        do {
                            int operand2 = num.pop();
                            int operand1 = num.pop();
                            char token = calculatorStack.pop();
                            int result = doMain(token, operand1, operand2);
                            num.push(result);
                        } while (calculatorStack.peek() != null &&
                                perc.get(values[i - 1]) > perc.get(calculatorStack.peek()));
                    }
                    num.push((int) values[i] - (int) ('0'));
                    calculatorStack.push(values[i - 1]);
                }
            }
        }

        while (calculatorStack.peek() != null){
            int operand2 =  num.pop();
            int operand1 =  num.pop();
            char token = calculatorStack.pop();
            int result = doMain(token,operand1, operand2);
            num.push(result);
        }
        return num.pop();
    }

    private static int getCount2(String calculator) {
        MyStack<Integer> num = new MyStack();
        MyStack<Character> calculatorStack = new MyStack();
        char[] values = calculator.toCharArray();
        for(int i = 0; i < values.length; i++){
            if(Character.isDigit(values[i])){
                num.push((int) values[i] - (int) ('0'));
            }else{
                if(
                        !calculatorStack.isEmpty() &&
                        perc.get(values[i]) <= perc.get(calculatorStack.peek())
                ) {
                    int operand2 = num.pop();
                    int operand1 = num.pop();
                    char token = calculatorStack.pop();
                    int result = doMain(token, operand1, operand2);
                    num.push(result);
                }
                calculatorStack.push(values[i]);
            }
        }

        while (calculatorStack.peek() != null){
            int operand2 =  num.pop();
            int operand1 =  num.pop();
            char token = calculatorStack.pop();
            int result = doMain(token,operand1, operand2);
            num.push(result);
        }
        return num.pop();
    }


    private static int getCount3(String calculator) {
        MyStack<Integer> numStack = new MyStack();
        MyStack<Character> calculatorStack = new MyStack();
        char[] values = calculator.toCharArray();
        for(int i = 0; i < values.length; i++){
            if(Character.isDigit(values[i])){
                numStack.push((int) values[i] - (int) ('0'));
            }else{
                if(values[i] == '('){
                    calculatorStack.push(values[i]);
                }else if((values[i] == ')')){
                    while(calculatorStack.peek() != '('){
                        int operand2 = numStack.pop();
                        int operand1 = numStack.pop();
                        char token = calculatorStack.pop();
                        int result = doMain(token, operand1, operand2);
                        numStack.push(result);
                    }
                    calculatorStack.pop();
                }else{
                    if(
                            !calculatorStack.isEmpty() &&
                                    perc.get(values[i]) <= perc.get(calculatorStack.peek())
                    ) {
                        int operand2 = numStack.pop();
                        int operand1 = numStack.pop();
                        char token = calculatorStack.pop();
                        int result = doMain(token, operand1, operand2);
                        numStack.push(result);
                    }
                    calculatorStack.push(values[i]);
                }
            }
        }

        while (calculatorStack.peek() != null){
            int operand2 =  numStack.pop();
            int operand1 =  numStack.pop();
            char token = calculatorStack.pop();
            int result = doMain(token,operand1, operand2);
            numStack.push(result);
        }
        return numStack.pop();
    }


    public static Integer doMain(char token, int operand1, int operand2){
        switch (token){
            case '*':
                return operand1 * operand2;
            case '+':
                return operand1 + operand2;
            case '-':
                return operand1 - operand2;
            case '/':
                return operand1 / operand2;
            default:
                return 0;
        }
    }

}
